﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LCA.Community.DAL.Model;
using LCA.Community.DAL.Interfaces;

namespace LCA.Community.DAL
{
    /// <summary>
    /// The repository for message data manipulation.
    /// </summary>
    public class MessagesRepository : BaseRepository<Message>, IMessagesRepository
    {
        #region Fields
        private IMessagesRecipentsRepository _messagesRecipentsRepository;
        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="MessagesRepository"/> class.
        /// </summary>
        /// <param name="dataServiceContext">The data service context.</param>
        /// <param name="messageRecipentsRepository">The message recipents repository.</param>
        /// <param name="usersRepository">The users repository.</param>
        public MessagesRepository(IDataServiceContext<Message> dataServiceContext, IMessagesRecipentsRepository messageRecipentsRepository)
            :base(dataServiceContext)
        {
            _messagesRecipentsRepository = messageRecipentsRepository;
        }

        /// <summary>
        /// Adds a message
        /// </summary>
        /// <param name="entity">The message.</param>
        public override void Add(Message entity)
        {
            base.Add(entity);

            if (entity.Recipents != null)
            {
                foreach (string recipent in entity.Recipents)
                {
                    var messageRecipent = new MessageRecipent(entity.RowKey, recipent);
                    _messagesRecipentsRepository.Add(messageRecipent);
                }
            }
        }

        /// <summary>
        /// Removes a message
        /// </summary>
        /// <param name="entity">The message.</param>
        public override void Delete(Message entity)
        {
            base.Delete(entity);

            _messagesRecipentsRepository.DeleteAllMessageRecipentsFromMessage(entity.RowKey);
        }

        /// <summary>
        /// Deletes all user messages.
        /// </summary>
        /// <param name="userID">The user ID.</param>
        public void DeleteAllUserMessages(string userID)
        {
            _messagesRecipentsRepository.DeleteAllReceiverMessageRecipents(userID);
            var messages = GetMessagesSentByUser(userID);

            messages.ForEach(m => Delete(m));
        }
        /// <summary>
        /// Gets the messages by user.
        /// </summary>
        /// <param name="userID">The user ID.</param>
        /// <returns>The messages.</returns>
        public List<Message> GetMessagesSentByUser(string userID)
        {
            return (from m in Entities
                    where m.User == userID
                    select m).ToList();
        }

        /// <summary>
        /// Gets the inbox of the elememt.
        /// </summary>
        /// <param name="userID">The element ID.</param>
        /// <returns>Element inbox</returns>
        public List<Message> GetInbox(string elementID)
        {
            return _messagesRecipentsRepository.GetMessageRecipentsByReceiver(elementID).Select(mr => Get(mr.Message)).OrderByDescending(m => m.Date).ToList();
        }

        /// <summary>
        /// Gets the volunteer help requests.
        /// </summary>
        /// <param name="userID">The user ID.</param>
        /// <returns>The help requests.</returns>
        public List<Message> GetVolunteerHelpRequests(string userID)
        {
            return (from m in Entities
                    from mr in _messagesRecipentsRepository.Entities.Where(mr => mr.Message == m.RowKey)
                    where mr.Recipent == userID && m.IsHelpRequest() 
                    select m).ToList();
        }

        /// <summary>
        /// Return the joining request sent by the user asking for being member of the group.
        /// </summary>
        /// <param name="groupId">The group id.</param>
        /// <param name="userId">The user id.</param>
        /// <returns>The message requesting joining to the group.</returns>
        public Message GetJoiningRequestMessage(string groupId, string userId)
        {
            var message = (from m in Entities
                           from mr in _messagesRecipentsRepository.GetMessageRecipentsByMessage(m.RowKey)
                           where m.Subject == JoiningRequestSubject && m.User == userId && mr.Recipent == groupId
                           select m).Distinct().FirstOrDefault();

            return message;
        }

        /// <summary>
        /// Return the friendship invitation from one user to another
        /// </summary>
        /// <param name="groupId">The user that sent the inviation.</param>
        /// <param name="userId">The user that was invited.</param>
        /// <returns>The message requesting friendship.</returns>
        public Message GetFriendshipRequestMessage(string userId, string friendId)
        {
            var message = (from m in Entities
                           from mr in _messagesRecipentsRepository.GetMessageRecipentsByMessage(m.RowKey)
                           where m.Subject == FriendshipRequestSubject && m.User == userId && mr.Recipent == friendId
                           select m).FirstOrDefault();

            return message;
        }

        /// <summary>
        /// Gets the help pool requests.
        /// </summary>
        /// <returns>The help pool requests.</returns>
        public List<Message> GetHelpPoolRequests()
        {
            return (from m in Entities
                    from mr in _messagesRecipentsRepository.Entities.Where(mr => mr.Message == m.RowKey)
                    where mr.Recipent == Message.HelpPool && m.IsHelpRequest()
                    select m).ToList();
        }

        /// <summary>
        /// Gets the help request sent by a user to a volunteer.
        /// </summary>
        /// <param name="userID">The user ID.</param>
        /// <param name="volunteerID">The volunteer ID.</param>
        /// <returns>Help request sent by the user to the volunteer.</returns>
        public Message GetHelpRequest(string userID, string volunteerID)
        {
            return (from m in Entities
                    from mr in _messagesRecipentsRepository.GetMessageRecipentsByMessage(m.RowKey)
                    where m.Subject == HelpRequestSubject && m.User == userID && mr.Recipent == volunteerID
                    select m).FirstOrDefault();
        }

        public string JoiningRequestSubject 
        { 
            get
            {
                return "Petición para unirse a un grupo";
            }
        }

        public string FriendshipRequestSubject
        {
            get
            {
                return "Petición de amistad";
            }
        }

        public string HelpRequestSubject
        {
            get
            {
                return "Help Request: Solicitud de ayuda"; 
            }
        }
    }
}
